package org.spring.core.io;

import org.tool.TipException;
import org.tool.core.lang.Assert;
import org.tool.reflect.ClassLoaderUtil;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Optional;

/**
 * 类路径资源的 {@link Resource} 实现。
 * 使用给定的 {@link ClassLoader} 或给定的 {@link Class} 来加载资源。
 * <p>
 * 如果类路径资源位于文件系统中，则支持解析为 {@code java.io.File}，但不支持 JAR 中的资源。始终支持解析为 URL。
 *
 * @author 李坤
 * @date 2022/4/16 10:59
 */
public class ClassPathResource implements Resource {

    /**
     * 资源路径
     */
    private final String path;

    /**
     * 资源加载类加载器
     */
    private ClassLoader classLoader;

    public ClassPathResource(String path) {
        this.path = ClassPathUtil.getClassPathResourcePath(path);
    }

    public ClassPathResource(String path, ClassLoader classLoader) {
        Assert.notNull(path, "路径不能为空");

        this.path = ClassPathUtil.getClassPathResourcePath(path);
        this.classLoader = Optional.ofNullable(classLoader).orElseGet(ClassLoaderUtil::getDefaultClassLoader);
    }

    @Override
    public InputStream getInputStream() throws IOException {
        InputStream inputStream;

        if (Objects.nonNull(this.classLoader)) {
            inputStream = this.classLoader.getResourceAsStream(this.path);
        } else {
            inputStream = ClassLoader.getSystemResourceAsStream(this.path);
        }
        if (Objects.isNull(inputStream)) {
            throw new FileNotFoundException(this.path + " 无法打开，因为它不存在");
        }
        return inputStream;
    }

    /**
     * 项目资源路径工具类
     */
    public static abstract class ClassPathUtil {

        /**
         * 资源路径前缀
         */
        public static final String CLASSPATH_URL_PREFIX = "classpath:";

        /**
         * 判断给定的路径是否是类路径资源
         *
         * @param path 路径
         *
         * @return 是否是类路径资源
         */
        public static boolean isClassPathResource(String path) {
            return path.startsWith(CLASSPATH_URL_PREFIX);
        }

        /**
         * 获取给定的路径的类路径资源
         *
         * @param path 路径
         *
         * @return 类路径资源
         */
        public static String getClassPathResourcePath(String path) {
            if (ClassPathUtil.isClassPathResource(path)) {
                return path.substring(CLASSPATH_URL_PREFIX.length());
            }
            throw new TipException("路径 " + path + " 不是类路径资源");
        }
    }

}
